/*
 * Copyright (c) 2020, RudyLo <luhuadong@163.com>
 *
 * SPDX-License-Identifier: MIT License
 *
 * Change Logs:
 * Date           Author       Notes
 * 2020-11-15     luhuadong    the first version
 */

#include <rtthread.h>
#include <rtdevice.h>
#include <board.h>

#include <string.h>
#include <stdio.h>
#include "ssd1306.h"
#include "ssd1306_tests.h"

void ssd1306_TestBorder()
{
    ssd1306_Fill(Black);

    uint32_t start = rt_tick_get();
    uint32_t end = start;
    uint8_t x = 0;
    uint8_t y = 0;
    do {
        ssd1306_DrawPixel(x, y, Black);

        if((y == 0) && (x < 127))
            x++;
        else if((x == 127) && (y < 31))
            y++;
        else if((y == 31) && (x > 0))
            x--;
        else
            y--;

        ssd1306_DrawPixel(x, y, White);
        ssd1306_UpdateScreen();

        // rt_thread_mdelay(5);
        end = rt_tick_get();
        // rt_kprintf("x:%d, y:%d, fps:%d\n", x, y, 1000/(end-start));
        // start = end;
    } while((end - start) < 30000);

    rt_thread_mdelay(1000);
}

void ssd1306_TestFonts()
{
    ssd1306_Fill(Black);
    ssd1306_SetCursor(2, 0);
    ssd1306_WriteString("Font 16x26", Font_16x26, White);
    ssd1306_SetCursor(2, 26);
    ssd1306_WriteString("Font 11x18", Font_11x18, White);
    ssd1306_SetCursor(2, 26+18);
    ssd1306_WriteString("Font 7x10", Font_7x10, White);
    ssd1306_SetCursor(2, 26+18+10);
    ssd1306_WriteString("Font 6x8", Font_6x8, White);
    ssd1306_UpdateScreen();
}

void ssd1306_TestFPS()
{
    ssd1306_Fill(White);

    uint32_t start = rt_tick_get();
    uint32_t end = start;
    int fps = 0;
    char message[] = "ABCDEFGHIJK";

    ssd1306_SetCursor(2,0);
    ssd1306_WriteString("Testing...", Font_11x18, Black);

    do {
        ssd1306_SetCursor(2, 18);
        ssd1306_WriteString(message, Font_11x18, Black);
        ssd1306_UpdateScreen();

        char ch = message[0];
        memmove(message, message+1, sizeof(message)-2);
        message[sizeof(message)-2] = ch;

        fps++;
        end = rt_tick_get();
    } while((end - start) < 5000);

    rt_thread_mdelay(1000);

    char buff[64];
    fps = (float)fps / ((end - start) / 1000.0);
    snprintf(buff, sizeof(buff), "~%d FPS", fps);

    ssd1306_Fill(White);
    ssd1306_SetCursor(2, 18);
    ssd1306_WriteString(buff, Font_11x18, Black);
    ssd1306_UpdateScreen();
}

void ssd1306_TestLine()
{
    ssd1306_Line(1,1,SSD1306_WIDTH - 1,SSD1306_HEIGHT - 1,White);
    ssd1306_Line(SSD1306_WIDTH - 1,1,1,SSD1306_HEIGHT - 1,White);
    ssd1306_UpdateScreen();
    return;
}

void ssd1306_TestRectangle()
{
    uint32_t delta;

    for(delta = 0; delta < 5; delta ++)
    {
        ssd1306_DrawRectangle(1 + (5*delta),1 + (5*delta) ,SSD1306_WIDTH-1 - (5*delta),SSD1306_HEIGHT-1 - (5*delta),White);
    }
    ssd1306_UpdateScreen();
    return;
}

void ssd1306_TestCircle()
{
    uint32_t delta;

    for(delta = 0; delta < 5; delta ++)
    {
        ssd1306_DrawCircle(20* delta+30, 30, 10, White);
    }
    ssd1306_UpdateScreen();
    return;
}

void ssd1306_TestArc()
{
    ssd1306_DrawArc(30, 30, 30, 20, 270, White);
    ssd1306_UpdateScreen();
    return;
}

void ssd1306_TestPolyline()
{
    SSD1306_VERTEX loc_vertex[] =
    {
        {35,40},
        {40,20},
        {45,28},
        {50,10},
        {45,16},
        {50,10},
        {53,16}
    };

    ssd1306_Polyline(loc_vertex,sizeof(loc_vertex)/sizeof(loc_vertex[0]),White);
    ssd1306_UpdateScreen();
    return;
}

void ssd1306_TestAll()
{
    ssd1306_Init();

    ssd1306_TestFPS();
    rt_thread_mdelay(3000);

    ssd1306_TestBorder();

    ssd1306_TestFonts();
    rt_thread_mdelay(3000);

    ssd1306_Fill(Black);
    ssd1306_TestRectangle();
    ssd1306_TestLine();
    rt_thread_mdelay(3000);

    ssd1306_Fill(Black);
    ssd1306_TestPolyline();
    rt_thread_mdelay(3000);

    ssd1306_Fill(Black);
    ssd1306_TestArc();
    rt_thread_mdelay(3000);

    ssd1306_Fill(Black);
    ssd1306_TestCircle();
    rt_thread_mdelay(3000);
}
void ssd1306_draw(int argc, char **argv)
{
    ssd1306_Init();

    if(argc == 4)
    {
        int x = atoi(argv[1]);
        int y = atoi(argv[2]);
        int color = atoi(argv[3]) == 0 ? Black : White;
        ssd1306_Fill(!color);
        ssd1306_DrawPixel(x, y, color);
        ssd1306_UpdateScreen();
        rt_kprintf("draw %d %d %d\n",x,y,color);
    }
}
#ifdef FINSH_USING_MSH
MSH_CMD_EXPORT(ssd1306_TestAll, test ssd1306 oled driver);
MSH_CMD_EXPORT(ssd1306_draw, draw pix x y color);
#endif
